﻿using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Threading;
using System.Web;
using Microsoft.VisualBasic;
using Slippor.Utility.WebWorker;

namespace Slippor.Douban.Radio.Assist
{
    public class Song
    {
        public static String DefaultTitle = AssistStringResource.Title;
        public static Song DefaultSong = new Song {_title = DefaultTitle};
        private FavState _faveState = FavState.Unknown;

        private String _title;
        public String Title
        {
            get { return _title; }
            set { _title = value; }
        }

        public FavState FaveState
        {
            get { return _faveState; }
            set { _faveState = value; }
        }

        private String _songID;
        public String SongID
        {
            get { return _songID; }
            set { _songID = value; }
        }

        private Album _album;
        public Album Album
        {
            get { return _album; }
        }

        private DateTime _listenTime = DateTime.Now;
        public DateTime ListenTime
        {
            get { return _listenTime; }
            set { _listenTime = value; }
        }

        public static void SetInfo(String bstrUrl, Song song)
        {
            const string pattern = @"douban.com/subject/(?<albumID>\d+)/";
            Match match = Regex.Match(bstrUrl, pattern);
            if(match.Success)
            {
                song._album = new Album(match.Groups["albumID"].Value);
                String url = bstrUrl;
                int tryTime = 3;
                String doc = String.Empty;
                var worker = new DoubanWebWorker();
                while (tryTime > 0)
                {
                    try
                    {
                        doc = worker.AchieveResponse(url, null, null, true, RequestMethod.Get);
                        tryTime = 0;
                    }
                    catch
                    {
                        tryTime--;
                        Thread.Sleep(2500);
                    }
                }
                const string datePattern = "发行时间:</span>(?<aTime>[^<]+)";
                match = Regex.Match(doc, datePattern);
                if (match.Success)
                {
                    song._album.PublishDate = HttpUtility.HtmlDecode(match.Groups["aTime"].Value).Trim();
                }
                String idPattern = String.Format(@"<tr><td>{0}</td>\W+td\W+a\Wid=""song-(?<songID>\d+)""", RadioUtility.VerifyRegex(song.Title));
                match = Regex.Match(doc, idPattern);
                if (match.Success)
                {
                    song._songID = match.Groups["songID"].Value;
                }
                const string infoPattern = "<h1>(?<aName>[\\w\\W]+?)</h1>[\\w\\W]*?(?:/lpic/(?<aCover>s\\d+).jpg[\\w\\W]*?)?<div id=\"info\">(?:[\\w\\W]*?<span><span class=\"pl\">\x8868\x6f14\x8005[\\w\\W]*?:(?<pName>[\\w\\W]+?)</span>)?[\\w\\W]*?</span>\\W*<strong class=\"ll rating_num\"[^>]*>(?<aMark>\\d+.\\d+)?</strong>";
                match = Regex.Match(doc, infoPattern);
                if (match.Success)
                {
                    var regex = new Regex("<.+?>", RegexOptions.IgnoreCase);
                    song._album.Name = HttpUtility.HtmlDecode(regex.Replace(match.Groups["aName"].Value, "")).Trim();
                    if(match.Groups["pName"] != null)
                    {
                        String singers = regex.Replace(match.Groups["pName"].Value, "");
                        singers = HttpUtility.HtmlDecode(singers).Trim();
                        if (singers.IndexOf('/') > 0)
                        {
                            List<String> singerList = new List<String>();
                            String[] singerArray = singers.Split('/');
                            foreach (String singer in singerArray)
                            {
                                String artist = CovertArtist(singer);
                                if (!singerList.Contains(artist))
                                {
                                    singerList.Add(artist);
                                }
                            }
                            song._album.Artists = singerList;
                        }
                        else
                        {
                            song._album.Artists = new List<string> { CovertArtist(singers) };
                        }
                    }
                    if (!String.IsNullOrEmpty(match.Groups["aMark"].Value))
                    {
                        song._album.Mark = Convert.ToDouble(match.Groups["aMark"].Value);
                    }
                    if (!String.IsNullOrEmpty(match.Groups["acover"].Value))
                    {
                        song._album.CoverID = match.Groups["acover"].Value;
                    }
                }
            }
        }

        private static readonly Dictionary<String, String> _converts = new Dictionary<String, String>
                                                                           {
            {"Penny","戴佩妮"},
            {"Eason Chan","陈奕迅"},
            {"Miriam Yeung","杨千嬅"},
            {"飞儿乐团","F.I.R."},
            {"林了祥","林子祥"},
        };

        private static string CovertArtist(string singer)
        {
            singer = Strings.StrConv(singer.Trim(), VbStrConv.SimplifiedChinese);
            if (_converts.ContainsKey(singer))
            {
                singer = _converts[singer];
            }
            return singer;
        }

        public override bool Equals(object obj)
        {
            Song song = obj as Song;
            if(song != null)
            {
                return song._title == _title && song._listenTime == _listenTime;
            }
            return false;
        }

        public override int GetHashCode()
        {
            return (int)_listenTime.Ticks;
        }
    }

    public class Album
    {
        public Album(String id)
        {
            _albumID = id;
        }

        public String ArtistString 
        { 
            get 
            {
                String toReturn = String.Empty;
                if (Artists != null)
                {
                    toReturn = String.Join("/", Artists.ToArray());
                }
                return toReturn;
            } 
        }

        public List<String> Artists { get; set; }

        public string Name { get; internal set; }
        public double Mark { get; internal set; }
        public string PublishDate { get; internal set; }

        private readonly String _albumID;
        public String AlbumID
        {
            get { return _albumID; }
        }

        private String _coverID;
        public String CoverID
        {
            get { return _coverID; }
            internal set { _coverID = value; }
        }
    }
}